#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>

#define CIMA     1
#define DIREITA  2
#define BAIXO    3
#define ESQUERDA 4

void inicio();
int menu();
int fase_1();
int fase_2();
void local_da_carta();
int aleatorio();

SDL_Surface* personagem = NULL;
SDL_Surface* personagem_otimizado = NULL;
int i = 0, j = 0;
int n_casa_anterior = 0;
SDL_Rect destino, destino1, destino2, destino3;
const int acrescimo_x = 2, acrescimo_y = 2;

/*
 * iniciar todas as funcoes do SDL
 * controle (conf. e menu)
 * jogo (enquanto não perde)
 * pontuação
 * finaliza
 */

 void inicio()
{
    SDL_Surface* abertura = NULL;
    SDL_Surface* tela = NULL;

    if(SDL_Init(SDL_INIT_EVERYTHING) != 0) // Inicia todos os subsistemas da SDL. Caso falhe, mostra o erro e encerra o programa;
    {
        printf("Erro: %s\n", SDL_GetError());
        exit(-1);
    }

    tela = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE); // Cria uma superfície na memória do sistema com 32 bits de cores;

    if(!tela) // Verifica se tela nao eh NULL;
    {
        printf("Erro ao carregar bitmap.\n");
        exit(-1);
    }

    abertura = SDL_LoadBMP("inicio.bmp");

    SDL_BlitSurface(abertura, NULL, tela, NULL); // Copia a imagem de uma superfície para outra;
    SDL_Flip(tela); // Copia a imagem da memória principal para a memória de vídeo;
    SDL_Delay(2500); // A imagem permanece na tela por 2,5 segundos;

    SDL_FreeSurface(abertura);
}

int colisao(SDL_Rect a,SDL_Rect b)
{
    return ncolide(a, b);
}

int ncolide(SDL_Rect a,SDL_Rect b)
{
    if((a.x+a.w < b.x) || (a.x > b.x+b.w) || (b.y+b.h < a.y) || (b.y > a.y+a.h))
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

int colide_alguem(SDL_Rect nova_pos)
{
    SDL_Rect bloco1 = {230, 335, 185, 140};
    SDL_Rect bloco2 = {0, 0, 90, 600};
    SDL_Rect bloco3 = {228, 83, 372, 129};
    SDL_Rect bloco4 = {734, 78, 64, 742};
    SDL_Rect bloco5 = {542, 327, 258, 273};

    return colisao(nova_pos, bloco1) || colisao(nova_pos, bloco2) || colisao(nova_pos, bloco3) || colisao(nova_pos, bloco4) || colisao(nova_pos, bloco5);
}

void mover_dogmail(int direcao)
{
    SDL_Rect nova_pos = destino;
    switch (direcao) {
    case CIMA:
        nova_pos.y -= 3;
        break;
    case DIREITA:
        nova_pos.x += 3;
        break;
    case BAIXO:
        nova_pos.y += 3;
        break;
    case ESQUERDA:
        nova_pos.x -= 3;
    }

    if (!colide_alguem(nova_pos))
    {
        switch (direcao)
        {
        case CIMA:
            personagem = SDL_LoadBMP("costas.bmp");
            personagem_otimizado = SDL_DisplayFormat(personagem);

            destino.y -= acrescimo_y;

            if (j%5 == 0)
            {
                i++;
            }
            j++;
            break;
        case DIREITA:
            personagem = SDL_LoadBMP("direita.bmp");
            personagem_otimizado = SDL_DisplayFormat(personagem);

            destino.x += acrescimo_x;

            if (j%5 == 0)
            {
                i++;
            }
            j++;
            break;
        case BAIXO:
            personagem = SDL_LoadBMP("frente.bmp");
            personagem_otimizado = SDL_DisplayFormat(personagem);

            destino.y += acrescimo_y;

            if (j%5 == 0)
            {
                i++;
            }
            j++;
            break;
        case ESQUERDA:
            personagem = SDL_LoadBMP("esquerda.bmp");
            personagem_otimizado = SDL_DisplayFormat(personagem);

            destino.x -= acrescimo_x;

            if (j%5 == 0)
            {
                i++;
            }
            j++;
        }
    }
}

int menu()
{
    Uint8 *teclado;

    SDL_Surface* tela = NULL;
    SDL_Surface* meu_menu = NULL;
    SDL_Surface* estagio1 = NULL;
    SDL_Event event;

    tela = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);
    meu_menu = SDL_LoadBMP("menu.bmp");
    SDL_BlitSurface(meu_menu, NULL, tela, NULL);
    SDL_Flip(tela);

    SDL_FreeSurface(meu_menu);

    teclado = SDL_GetKeyState(0);
    SDL_WaitEvent(&event);

    if(teclado[SDLK_1])
    {

        estagio1 = SDL_LoadBMP("estagio1.bmp");
        SDL_BlitSurface(estagio1, NULL, tela, NULL);
        SDL_Flip(tela);

        SDL_Delay(3000);
        SDL_FreeSurface(estagio1);

        return 1;

    }
    if(teclado[SDLK_2])
    {
        meu_menu = SDL_LoadBMP("instrucoes.bmp");
        SDL_BlitSurface(meu_menu, NULL, tela, NULL);
        SDL_Flip(tela);

        teclado = SDL_GetKeyState(0);
        SDL_WaitEvent(&event);

        // continua esperando ate que uma tecla seja pressionada

        while (event.type != SDL_KEYDOWN)
        {
            SDL_WaitEvent(&event);
        }
    }
    if(teclado[SDLK_3])
    {
        meu_menu = SDL_LoadBMP("sobre.bmp");
        SDL_BlitSurface(meu_menu, NULL, tela, NULL);
        SDL_Flip(tela);

        teclado = SDL_GetKeyState(0);
        SDL_WaitEvent(&event);

        // continua esperando ate que uma tecla seja pressionada
        while (event.type != SDL_KEYDOWN)
        {
            SDL_WaitEvent(&event);
        }
    }
    if(teclado[SDLK_4] || event.type == SDL_QUIT)
    {
        return 0; // Encerra;
    }
    else
    {
        SDL_WaitEvent(&event);
        return menu();
    }
}

int aleatorio()
{
    int n;

    srand (time(NULL));

    n = rand()%10+1;

    return n;
}

void local_da_carta(Sint16* x, Sint16* y)
{
    int n_casa;

    n_casa = aleatorio();

    while(n_casa == n_casa_anterior)
    {
        n_casa = aleatorio();
    }

    n_casa_anterior = n_casa;

    switch (n_casa)
    {
        case 1:
            *x = 244;
            *y = 26;
            break;
        case 2:
            *x = 372;
            *y = 26;
            break;
        case 3:
            *x = 512;
            *y = 26;
            break;
        case 4:
            *x = 274;
            *y = 279;
            break;
        case 5:
            *x = 329;
            *y = 279;
            break;
        case 6:
            *x = 495;
            *y = 279;
            break;
        case 7:
            *x = 288;
            *y = 540;
            break;
        case 8:
            *x = 130;
            *y = 130;
            break;
        case 9:
            *x = 130;
            *y = 30;
            break;
        case 10:
            *x = 677;
            *y = 266;
            break;
    }
}

int fase_1()
{
    int k = 0, l = 0;
    int acrescimo_x1 = 3;
    int cartas_entregues = 0;
    const int dog_altura = 57, dog_largura = 29;
    const int tela_altura = 600, tela_largura = 800, color_bits = 32;
    const int inimigo_altura = 47, inimigo_largura = 55;
    const int n_cartas_altura = 14, n_cartas_largura = 21;
    const int seta_altura = 35, seta_largura = 25;
    Uint8* teclado;

comeco:

    if (menu())
    {
        l = 0;

        SDL_Surface* tela = NULL;
        SDL_Surface* inimigo = NULL;
        SDL_Surface* inimigo_otimizado = NULL;
        SDL_Surface* n_cartas = NULL;
        SDL_Surface* n_cartas_otimizadas = NULL;
        SDL_Surface* seta = NULL;
        SDL_Surface* seta_otimizada = NULL;
        SDL_Surface* cenario = NULL;
        SDL_Surface* fim = NULL;

        SDL_Rect fonte; // personagem
        SDL_Rect fonte1; // inimigo
        SDL_Rect fonte2; // número de cartas
        SDL_Rect fonte3; // carta

        SDL_Event evento;

        tela = SDL_SetVideoMode(tela_largura, tela_altura, color_bits, SDL_SWSURFACE);

        if(!tela)
        {
            printf("Erro ao carregar imagem.\n");
            exit(-1);
        }

        cenario = SDL_LoadBMP("cenario.bmp");

        SDL_BlitSurface(cenario, NULL, tela, NULL);
        SDL_Flip(tela);

        personagem = SDL_LoadBMP("frente.bmp");
        personagem_otimizado = SDL_DisplayFormat(personagem);

        if(personagem_otimizado != NULL)
        {
            Uint32 color_key = SDL_MapRGB(personagem_otimizado->format, 255, 0, 0); // mapeia o vermelho
            SDL_SetColorKey(personagem_otimizado, SDL_SRCCOLORKEY, color_key); // tira o vermelho mapeado da imagem do personagem
        }

        fonte.x = 0;
        fonte.y = 0;
        fonte.w = dog_largura;
        fonte.h = dog_altura;

        destino.x =160;
        destino.y = 555;
        destino.w = dog_largura;
        destino.h = dog_altura;

        inimigo = SDL_LoadBMP("inimigo_dir.bmp");
        inimigo_otimizado = SDL_DisplayFormat(inimigo);

        if(inimigo_otimizado != NULL)
        {
            Uint32 color_key = SDL_MapRGB(inimigo_otimizado->format, 255, 0, 0);
            SDL_SetColorKey(inimigo_otimizado, SDL_SRCCOLORKEY, color_key);
        }

        fonte1.x = 0;
        fonte1.y = 0;
        fonte1.w = inimigo_largura;
        fonte1.h = inimigo_altura;

        destino1.x = 80;
        destino1.y = 250;
        destino1.w = inimigo_largura;
        destino1.h = inimigo_altura;

        n_cartas = SDL_LoadBMP("n_cartas.bmp");
        n_cartas_otimizadas = SDL_DisplayFormat(n_cartas);

        if(n_cartas_otimizadas != NULL)
        {
            Uint32 color_key = SDL_MapRGB(n_cartas_otimizadas->format, 255, 0, 0);
            SDL_SetColorKey(n_cartas_otimizadas, SDL_SRCCOLORKEY, color_key);
        }

        fonte2.x = 0;
        fonte2.y = 0;
        fonte2.w = n_cartas_largura;
        fonte2.h = n_cartas_altura;

        destino2.x = 565;
        destino2.y = 545;
        destino2.w = n_cartas_altura;
        destino2.h = n_cartas_largura;

        seta = SDL_LoadBMP("seta.bmp");
        seta_otimizada = SDL_DisplayFormat(seta);

        if(seta_otimizada != NULL)
        {
            Uint32 color_key = SDL_MapRGB(seta_otimizada->format, 255, 0, 0);
            SDL_SetColorKey(seta_otimizada, SDL_SRCCOLORKEY, color_key);
        }

        fonte3.x = 0;
        fonte3.y = 0;
        fonte3.w = seta_largura;
        fonte3.h = seta_altura;

        destino3.x = 0;
        destino3.y = 0;
        destino3.w = seta_largura;
        destino3.h = seta_altura;

        SDL_FreeSurface(tela);



        do
        {
            SDL_BlitSurface(cenario, NULL, tela, NULL);

            SDL_PollEvent(&evento);

/*            switch(evento.type)
            {
            case SDL_KEYDOWN:

                printf("Tecla pressionada.\n");
                break;

            case SDL_KEYUP:

                printf("Tecla solta.\n");
                break;

            case SDL_QUIT:

                printf("Saída requerida.\n");
            }
 */

            SDL_PumpEvents();
            teclado = SDL_GetKeyState(0);

            if (teclado[SDLK_UP])
            {
                mover_dogmail(CIMA);
            }
            if (teclado[SDLK_DOWN])
            {
                mover_dogmail(BAIXO);
            }
            if (teclado[SDLK_RIGHT])
            {
                mover_dogmail(DIREITA);
            }
            if (teclado[SDLK_LEFT])
            {
                mover_dogmail(ESQUERDA);
            }

            if(teclado[SDLK_ESCAPE]) // Pausa o jogo;
            {
                SDL_WaitEvent(&evento);
                SDL_WaitEvent(&evento);
            }

            if(colisao(destino,destino1)) // Detecta a colisão entre personagem e inimigo;
            {
                //printf("colisao\n");

                fim = SDL_LoadBMP("fim.bmp");
                SDL_BlitSurface(fim, NULL, tela, NULL);
                SDL_Flip(tela);

                SDL_Delay(3500);
                SDL_FreeSurface(fim);

                goto comeco;
            }

            if(personagem_otimizado != NULL)
            {
                Uint32 color_key = SDL_MapRGB(personagem_otimizado->format, 255, 0, 0);
                SDL_SetColorKey(personagem_otimizado, SDL_SRCCOLORKEY, color_key);
            }

            fonte.x = (i % 2) * dog_largura;

            if ((destino.y + dog_altura + acrescimo_y > tela_altura) || (destino.y + acrescimo_y < 0)) // Impede o personagem de atravessar a tela;
            {
                destino.y -= acrescimo_y;
            }
            if ((destino.x + dog_largura + acrescimo_x > tela_largura) || (destino.x + acrescimo_x < 0))
            {
                destino.x -= acrescimo_x;
            }

            SDL_BlitSurface(personagem_otimizado, &fonte, tela, &destino);


            if ((destino1.x + inimigo_largura + acrescimo_x1 > 800) || (destino1.x + acrescimo_x1 < 0)) // Impede o inimigo de atravessar a tela;
            {
                acrescimo_x1 = -acrescimo_x1;
            }

            destino1.x += acrescimo_x1;

            fonte1.x = (k%2) * inimigo_largura; // Mudar o sprite do inimigo;

            if (acrescimo_x1 > 0) // Saber se o imimigo está se movendo para a direita ou para a esquerda;
            {
                inimigo = SDL_LoadBMP("inimigo_dir.bmp");
                inimigo_otimizado = SDL_DisplayFormat(inimigo);
            }
            else
            {
                inimigo = SDL_LoadBMP("inimigo_esq.bmp");
                inimigo_otimizado = SDL_DisplayFormat(inimigo);
            }

            if(inimigo_otimizado != NULL)
            {
                Uint32 color_key = SDL_MapRGB(inimigo_otimizado->format, 255, 0, 0);
                SDL_SetColorKey(inimigo_otimizado, SDL_SRCCOLORKEY, color_key);
            }

            SDL_BlitSurface(inimigo_otimizado, &fonte1, tela, &destino1);


            fonte2.w = (10 - cartas_entregues) * n_cartas_largura;

            n_cartas = SDL_LoadBMP("n_cartas.bmp");
            n_cartas_otimizadas = SDL_DisplayFormat(n_cartas);

            if(n_cartas_otimizadas != NULL)
            {
                Uint32 color_key = SDL_MapRGB(n_cartas_otimizadas->format, 255, 0, 0);
                SDL_SetColorKey(n_cartas_otimizadas, SDL_SRCCOLORKEY, color_key);
            }

            SDL_BlitSurface(n_cartas_otimizadas, &fonte2, tela, &destino2);

            if (l == 0) // Pega o local da primeira carta
            {
                local_da_carta(&destino3.x, &destino3.y);
            }

            if(colisao(destino,destino3)) // Detecta a colisão entre personagem e carta para obter um novo local de carta;
            {
                //printf("colisao\n");
                cartas_entregues++;
                local_da_carta(&destino3.x, &destino3.y);
            }

            if (cartas_entregues == 10) // Se entregar todas as cartas, passa para a próxima fase;
            {
                //printf("colisao\n");

                cenario = SDL_LoadBMP("ganhou.bmp");
                SDL_BlitSurface(cenario, NULL, tela, NULL);
                SDL_Flip(tela);

                SDL_Delay(3500);
                SDL_FreeSurface(cenario);

                return 1;
            }

            seta = SDL_LoadBMP("seta.bmp");
            seta_otimizada = SDL_DisplayFormat(seta);

            if(seta_otimizada != NULL)
            {
                Uint32 color_key = SDL_MapRGB(seta_otimizada->format, 255, 0, 0);
                SDL_SetColorKey(seta_otimizada, SDL_SRCCOLORKEY, color_key);
            }

            SDL_BlitSurface(seta_otimizada, &fonte3, tela, &destino3);

            SDL_Flip(tela);

            if (l%15 == 0)
            {
                k++;
            }
            l++;

        }
        while(evento.type != SDL_QUIT);

        SDL_Quit();
    }

    return 0;
}

int main()
{
    comeco:

    inicio();

    if (fase_1())
    {

        goto comeco;
        //fase_2;
    }

}
